#!/usr/bin/env python
# encoding: utf-8
from audio import *
from matrice import *

class AudioServer:
    def __init__(self):
        self.server = s
        self.getAudioDrivers()
        self.server.setOutputDevice(self.defaultOutputIndex)
        self.server.setInputDevice(self.defaultInputIndex)

    def closeServer(self):
        if self.server.getIsStarted():
            self.server.stop()

    def changeAudioDriver(self, driver):
        pos = self.outputDriverNames.index(driver)
        self.defaultOutputIndex = self.outputDriverIndexes[pos]

        self.closeServer()
        if self.server.getIsBooted():
            self.server.shutdown()
            print 'Shutdown'
        self.server.setOutputDevice(self.defaultOutputIndex)
        self.server.boot()
        self.server.start()
        print 'Restart'

    def changeAudioDriver1(self, driver):
        pos1 = self.inputDriverNames.index(driver)
        self.defaultInputIndex = self.inputDriverIndexes[pos1]

        self.closeServer()
        if self.server.getIsBooted():
            self.server.shutdown()
            print 'Shutdown'
        self.server.setInputDevice(self.defaultInputIndex)
        self.server.boot()
        self.server.start()
        print 'Restart'

    def getAudioDrivers(self):
        self.outputDriverNames, self.outputDriverIndexes = pa_get_output_devices()
        self.inputDriverNames, self.inputDriverIndexes = pa_get_input_devices()

        self.defaultOutputIndex = pa_get_default_output()
        self.defaultInputIndex = pa_get_default_input()

        pos = self.outputDriverIndexes.index(self.defaultOutputIndex)
        pos1 = self.inputDriverIndexes.index(self.defaultInputIndex)

        self.defaultOutputName = self.outputDriverNames[pos]
        self.defaultInputName = self.inputDriverNames[pos1]

    def getAudioDriverNames(self):
        return self.outputDriverNames, self.defaultOutputName

    def getAudioDriverNames1(self):
        return self.inputDriverNames, self.defaultInputName

##########################

# Mixeur de sources versus FX
class Mixeur:
    def __init__(self, audio):
        self.sonram = audio.sig()
        self.entree1 = audio.sig1()
        self.looping = audio.loop()
        self.mm = Mixer(outs = 3, chnls = 2, time = 0.25)
        self.mm.addInput(0, self.sonram)
        self.mm.addInput(1, self.entree1)
        self.mm.addInput(4, self.looping)
        # Amplitude de son ram vers Direct Out
        self.mm.setAmp(0, 0, 0)
        # Amplitude de entree 1 vers Direct Out
        self.mm.setAmp(1, 0, 0)
        # Amplitude de son ram vers Bit Reducer
        self.mm.setAmp(0, 1, 0)
        # Amplitude de entree 1 vers Bit Reducer
        self.mm.setAmp(1, 1, 0)
        # Amplitude de son ram vers Reverb
        self.mm.setAmp(0, 2, 0)
        # Amplitude de son entree 1 vers Reverb
        self.mm.setAmp(1, 2, 0)
        # Amplitude de loop vers Direct Out
        self.mm.setAmp(4, 0, 0)
        # Amplitude de loop vers Bit Reducer
        self.mm.setAmp(4, 1, 0)
        # Amplitude de loop vers Reverb
        self.mm.setAmp(4, 2, 0)

        # Sortie directe
        self.direct = (self.mm[0])
        # Sortie vers Bit Reducer
        self.fx1 = (self.mm[1])
        # Sortie vers Reverb
        self.fx2 = (self.mm[2])

    # Sortie Direct Out
    def mixeurOut0(self):
        return self.direct
    # Sortie FX 1 - Bit Reducer
    def mixeurOut1(self):
        return self.fx1
    # Sortie FX 2 - Reverb
    def mixeurOut2(self):
        return self.fx2

class DirectOut:
    def __init__(self, mixeur):
        self.audio =  mixeur.mixeurOut0()
        self.directOut = Sig(self.audio).out()

class BitReducer:
    def __init__(self, audio):
        self.audio = mixeur.mixeurOut1()
        self.valeurminimale = 5
        self.valeurmaximale = 10
        self.valeurminimalescale = 100
        self.valeurmaximalescale = 1000
        self.metscale = Beat(time=.125, taps=16, w1=90, w2=50, w3=30).play()
        self.metbit = Beat(time=.125, taps=16, w1=90, w2=50, w3=30).play()
        initchoicebit = [i for i in range(self.valeurminimale, self.valeurmaximale)]
        initchoicescale = [i * 0.001 for i in range (self.valeurminimalescale, self.valeurmaximalescale)]
        self.sequencebitchoice = TrigChoice(self.metbit, choice=initchoicebit)
        self.sequencescalechoice = TrigChoice(self.metscale, choice=initchoicescale)
        self.bitreduce = Degrade(self.audio, bitdepth=self.sequencebitchoice, srscale=self.sequencescalechoice).out()

    def updateScale(self):
        self.sequencescalechoice.choice = [i * 0.001 for i in range(self.valeurminimalescale, self.valeurmaximalescale)]

    def updateSequence(self):
        self.sequencebitchoice.choice = [i for i in range(self.valeurminimale, self.valeurmaximale)]

    def updateBeatScale(self, value):
        self.metscale.time = value

    def updateBeatBit(self, value):
        self.metbit.time = value

    def retourBR(self):
        return self.bitreduce

class Reverb:
    def __init__(self, audio):
        self.audio = mixeur.mixeurOut2()
        self.valeurminimalesize = 0
        self.valeurmaximalesize = 100
        self.valeurminimaledamp = 0
        self.valeurmaximaledamp = 100
        self.metsize = Beat(time=.125, taps=16, w1=90, w2=50, w3=30).play()
        self.metdamp = Beat(time=.125, taps=16, w1=90, w2=50, w3=30).play()
        initchoicesize = [i*0.01 for i in range(self.valeurminimalesize, self.valeurmaximalesize)]
        initdampchoice = [i*0.01 for i in range(self.valeurminimaledamp, self.valeurmaximaledamp)]
        self.sequencesizechoice = TrigChoice(self.metsize, choice = initchoicesize)
        self.sequencedampchoice = TrigChoice(self.metdamp, choice = initdampchoice)
        self.reverb = Freeverb(self.audio, size=self.sequencesizechoice, damp=self.sequencedampchoice, bal = 1).out()

    def updateSize(self):
        self.sequencesizechoice.choice = [i * 0.01 for i in range(self.valeurminimalesize, self.valeurmaximalesize)]

    def updateDamp(self):
        self.sequencedampchoice.choice = [i* 0.01 for i in range(self.valeurminimaledamp, self.valeurmaximaledamp)]

    def updateBeatSize(self, value):
        self.metsize.time = value

    def updateDampTime(self, value):
        self.metdamp.time = value

    def retourReverb(self):
        return self.reverb

############

class Audio():
    def __init__(self):

############# Sources

        self.table = SndTable([SNDS_PATH+"/transparent.aif",SNDS_PATH+"/transparent.aif"])
        self.input = Looper(table=self.table, pitch = 1, start=0, dur = 1, xfade = 10, startfromloop = True, mul = 1, interp =4 , autosmooth = True)
        self.input

        self.scin1 = Input(chnl = 0, mul = 1)
        self.scin2 = Input(chnl = 1, mul = 1)
        self.scin3 = Input(chnl = 2, mul = 1)
        self.scin4 = Input(chnl = 3, mul = 1)
        # Choix input looper
        self.inputsc = Selector(inputs = [self.scin1, self.scin2, self.scin3, self.scin4], voice=0., mul=1)
        self.inputsc
        # Choix input son direct
        self.input1 = Selector(inputs = [self.scin1, self.scin2, self.scin3, self.scin4], voice=0., mul=1)
        self.input1

        self.lentable = self.table.getDur(False)
        self.startsl = None
        self.endsl = None

        # Looper
        self.tab = NewTable(8)
        self.trigg = Trig().stop()
        self.rec = TrigTableRec(self.inputsc, self.trigg, self.tab)
        self.pitchboucle = 1
        self.looprec = Looper(table = self.tab, pitch=self.pitchboucle, start=0, dur=1, xfade=20, mode=1, xfadeshape=0, startfromloop=True, interp=2, autosmooth=False, mul=1, add=0)

    # Retour du signal audio Ram
    def sig(self):
        return self.input

    # Retour du signal audio entree 1
    def sig1(self):
        return self.input1

    def loop(self):
        return self.looprec

    # Load nouveau son
    def changeTable(self, snd):
        self.table.sound = snd
        self.input.freq = self.table.getRate()
        self.lentable = self.table.getDur(False)
        if self.startsl != None:
            print self.lentable
            self.startsl.SetRange(0, self.lentable)
            self.endsl.SetRange(0, self.lentable)
            self.fade1.SetRange(0, self.lentable)

    def setSliders(self, start, end, fadex):
        self.startsl = start
        self.endsl = end
        self.fade1 = fadex

# Son Ram
audio = Audio()

# Mixeur
mixeur = Mixeur(audio)

# Direct Out
directOut = DirectOut(mixeur)

# Effets
bitreduce = BitReducer(audio)
reverb = Reverb(audio)

# Mixeur FX dans FX (update du mixeur apres les FX)
mixeur.mm.addInput(2, bitreduce.retourBR())
mixeur.mm.addInput(3, reverb.retourReverb())

# Amplitude de bitreducer dans Reverb / Amplitude de Reverb dans bitreducer
mixeur.mm.setAmp(2, 2, 0)
mixeur.mm.setAmp(3, 1, 0)